#include <iostream>
#include <vector>
#include <memory>

class Test
{
public:
    Test() { a = new int; }

    // 拷贝构造
    Test(const Test &t)
    {
        std::cout << "拷贝构造!\n";
        a = new int(*t.a);
    }

    // 移动构造函数（右值引用）
    // 目的：夺取内存所有权
    Test(Test &&t)
    {
        std::cout << "移动构造!\n";
        a = t.a;
        t.a = nullptr;
    }

private:
    int *a;
};

int main()
{
#if 0
    // 左值：有内存的值
    // 右值：常量（无内存），将亡值（有内存，C++11引入的）RVO优化

    int a = 10;
    int &b = a; // 左值引用

    // int &c = 10; // 右值不能直接引用
    // const int &c = 10; // 常引用（这样就可以引用右值了）

    int &&c = 10; // 右值引用
    
    // int &&c = a; // 右值引用去引用左值是不成立的

    // 移动语义
    int &&c = std::move(a); // 把左值变成一个右值，再对其进行引用

    std::vector<int> v = {1, 2, 3, 4, 5, };
    // ......

    std::vector<int> v2 = v;
#endif

#if 0
    Test t1;
    // Test t2 = t1;

    // 想要调移动构造，就必须赋右值
    // move函数：能够将左值变成右值
    Test t2 = std::move(t1);
#endif

#if 0
    // 所有的STL都支持移动语义

    std::vector<std::vector<int>> v;

    std::vector<int> v1 = {1, 2, 3, 4, 5};
    v.push_back(std::move(v1));
#endif

#if 1
    std::unique_ptr<int> p = std::make_unique<int>();
    *p = 10;
    std::cout << *p <<std::endl;
    auto p1 = std::move(p);
    std::cout << *p1 << std::endl;
#endif

#if 0
    // 智能指针想要塞进容器得用移动语义

    std::vector<std::unique_ptr<int>> v;

    std::unique_ptr<int> p = std::make_unique<int>();
    v.push_back(std::move(p)); // 使用移动语义会夺走其内存，就不能再使用了

#endif




    return 0;
}